<?php
declare (strict_types=1);

namespace app\admin\service\base;

use aliyun\AliyunOss;
use app\admin\model\base\Admin;
use app\admin\model\base\AdminRole;
use app\admin\model\base\AdminRoleAccess;
use app\admin\model\base\Classes;
use app\admin\model\base\Duties;
use app\admin\model\base\Grades;
use app\admin\model\base\Special;
use app\admin\validates\AdminValidate;
use app\BaseService;
use auth\Auth;
use ciphertext\RsaPassword;
use PhpOffice\PhpSpreadsheet\IOFactory;
use think\exception\ValidateException;
use think\facade\Db;
use think\Model;
use think\response\Json;
use upload\ImgUpload;

/**
 * 管理员权限中心
 */
class AdminService extends BaseService
{
    /**
     * 管理员登录
     * @param int $phone
     * @param string $password
     * @param string $platform
     * @return Json
     */
    public function login(int $phone, string $password, string $platform): Json
    {
        //查询
        $user = Admin::findOne(['phone' => $phone, 'closed' => 0, 'enable' => 1]);
        if (!$user) {
            return jsonReturn(0, [], '管理员不存在');
        }
        //先解密密码
        $password = RsaPassword::privateDecrypt($password);
        //验证账号密码
        if (!password_verify($password . $user['safe_code'], $user['password'])) {
            return jsonReturn(0, ['err' => '密码不正确'], '密码不正确');
        }
        //更新数据库
        Admin::update(['login_ip' => request()->ip(), 'login_time' => time()], ['id' => $user['id']]);
        //登录程序
        $jst_data = JwtService::authorizations($platform, intval($user['id']));
        if (!$jst_data['bool']) {
            return jsonReturn(0, [], '签发token失败');
        }
        return jsonReturn(1, [], '登录成功');
    }

    /**
     * 导入学生
     * @param array $params
     * @return Json
     */
    public function import(array $params):Json
    {
        // 获取表单上传文件
        $file[] = request()->file('file');
        // 验证文件大小，名称等是否正确
        validate(['file' => 'filesize:51200|fileExt:xls,xlsx'])
            ->check(['file'=>$file[0] ?? '']);
        $savename =\think\facade\Filesystem::disk('public')->putFile('upload', $file[0]);
        $fileExtendName = substr(strrchr($savename, '.'), 1);
        // 有Xls和Xlsx格式两种
        if ($fileExtendName == 'xlsx') {
            $objReader = IOFactory::createReader('Xlsx');
        } else {
            $objReader = IOFactory::createReader('Xls');
        }
        $objReader->setReadDataOnly(TRUE);
        // 读取文件，tp6默认上传的文件，在runtime的相应目录下，可根据实际情况自己更改
        $objPHPExcel = $objReader->load(public_path().$savename);
        $sheet = $objPHPExcel->getSheet(0);   //excel中的第一张sheet
        $highestRow = $sheet->getHighestRow();       // 取得总行数
        $highestColumn = $sheet->getHighestColumn();   // 取得总列数
        \PhpOffice\PhpSpreadsheet\Cell\Coordinate::columnIndexFromString($highestColumn);
        $lines = $highestRow - 1;
        if ($lines <= 0) {
            throw new \Exception('数据不能为空');
        }
        Db::startTrans();
        try {

            //查询年级和班级
            $AdminRole = AdminRole::select()->toArray();
            $duties = Duties::select()->toArray();
            $special = Special::select()->toArray();
            $ids = array_column($AdminRole,'id','role_name');
            $duties_ids = array_column($duties,'id','name');
            $special_ids = array_column($special,'id','name');
            //循环读取excel表格，整合成数组。如果是不指定key的二维，就用$data[i][j]表示。
            $dataArr = [];
            $dataArr2 = [];
            for ($j = 2; $j <= $highestRow; $j++) {
                $phone = $objPHPExcel->getActiveSheet()->getCell("B" . $j)->getValue();
                $name = $objPHPExcel->getActiveSheet()->getCell("A" . $j)->getValue() ? trim($objPHPExcel->getActiveSheet()->getCell("A" . $j)->getValue()) : '';
                $duties = $objPHPExcel->getActiveSheet()->getCell("C" . $j)->getValue() ? trim($objPHPExcel->getActiveSheet()->getCell("C" . $j)->getValue()) : '';
                $special = $objPHPExcel->getActiveSheet()->getCell("D" . $j)->getValue() ? trim($objPHPExcel->getActiveSheet()->getCell("D" . $j)->getValue()) : '';
                $role = $objPHPExcel->getActiveSheet()->getCell("E" . $j)->getValue() ? trim($objPHPExcel->getActiveSheet()->getCell("E" . $j)->getValue()) : '';
                $mobile = $objPHPExcel->getActiveSheet()->getCell("F" . $j)->getValue() ? $objPHPExcel->getActiveSheet()->getCell("F" . $j)->getValue() : '';
                $desc = $objPHPExcel->getActiveSheet()->getCell("G" . $j)->getValue() ? trim($objPHPExcel->getActiveSheet()->getCell("G" . $j)->getValue()) : '';
                //处理教师角色
                if($phone != '' && $name != '' && isset($duties_ids[$duties]) && isset($ids[$role]) && isset($special_ids[$special])){
                    $safe_code = substr(md5(uniqid()), 5, 10);
                    $value = '123456' . $safe_code;
                    $password = password_hash($value, PASSWORD_DEFAULT);
                    //处理教师的角色导入
                    $dataArr[] = $data = [
                        'phone'=>$phone,
                        'name'=>$name,
                        'create_user'=>WS_ADMIN_ID,
                        'special_id'=>$special_ids[$special],
                        'duties_id'=>$duties_ids[$duties],
                        'desc'=>$desc ?? '',
                        'mobile'=>$mobile ?? '',
                        'avatar'=>'',
                        'safe_code'=>$safe_code,
                        'password'=>$password,
                        'create_time'=>time(),
                        'update_time'=>time(),
                    ];
                    $res = Admin::create($data);
                    if($res){
                        $dataArr2[] = [
                            'admin_id'=>$res->id,
                            'role_id'=>$ids[$role],
                        ];
                    }
                }
            }
            $model = new AdminRoleAccess();
            $res = $model->saveAll($dataArr2);
            if(!$res){
                throw new \Exception('导入数据库失败');
            }
            Db::commit();
            return jsonReturn(1, ['num'=>count($dataArr)]);
        } catch (\think\exception\ValidateException $e) {
            Db::rollback();
            return jsonReturn(0, [],$e->getMessage());
        }
    }

    /**
     * 管理员退出
     * @return Json
     */
    public function logout(string $platform): Json
    {
        JwtService::userAdminLogout(WS_ADMIN_ID, $platform);
        return jsonReturn(1, [], '退出成功');
    }

    /**
     * 获取管理员信息
     * @return Json
     */
    public function getInfo(): Json
    {
        $admin_id = WS_ADMIN_ID;
        $user = Admin::findOne(['id' => $admin_id, 'closed' => 0,]);
        if (!$user) {
            return jsonReturn(0, [], '管理员不存在');
        }
        /**
         * 管理员信息
         * @return array
         */
        $user = function () use ($user) {
            $AliyunOss = new AliyunOss();
            $user['avatar'] = $user['avatar'] ?: config('ws_config.avatar');
            $user['avatar'] = $AliyunOss->getObjectUrl($user['avatar']);
            unset($user['safe_code']);
            unset($user['password']);
            return $user;
        };
        /**
         * 获取权限信息
         * @return array|string[]
         */
        $permissions = function () use ($admin_id) {
            //超级管理员显示所有权限
            if ($admin_id == 1) {
                return ['*:*:*'];
            } else {
                $Auth = new Auth();
                $list = $Auth->getAuthList2($admin_id);
                return array_merge(array_filter($list));
            }
        };
        //组装数组
        $data = [
            'user' => $user(),
            'permissions' => $permissions(),
            'roles' => [],
        ];
        return jsonReturn(1, $data);
    }

    /**
     * 管理员列表
     * @param array $params
     * @return Json
     */
    public function list(array $params): Json
    {
        $where[] = ['closed', '=', 0];
        //搜索名称
        if ($params['name']) {
            $where[] = ['name', 'like', '%' . $params['name'] . '%'];
        }
        //搜索手机号
        if ($params['phone']) {
            $where[] = ['phone', '=', $params['phone']];
        }
        //搜索状态
        if (isset($params['enable']) && in_array($params['enable'], [0, 1])) {
            $where[] = ['enable', '=', $params['enable']];
        }
        //创建时间筛选
        if ($params['start_time'] && $params['end_time']) {
            $start_time = (int)$params['start_time'];
            $end_time = (int)$params['end_time'];
            $where[] = ['create_time', 'between', [$start_time, $end_time]];
        }
        //获取列表
        $data = Admin::getList($where, $params['page'], $params['limit'], 'enable desc,id desc');
        return jsonReturn(1, $data);
    }

    /**
     * 添加管理员
     * @param array $params
     * @return Json
     */
    public function add(array $params): Json
    {
        //验证手机号是否唯一
        $where = ['phone' => $params['phone'], 'closed' => 0];
        $res = Admin::findOne($where);
        if ($res) {
            return jsonReturn(0, [], '此工号已存在');
        }
        //先解密密码
        $params['password'] = RsaPassword::privateDecrypt($params['password']);
        //数据验证
        try {
            validate(AdminValidate::class)->scene('add')->check($params);
        } catch (ValidateException $e) {
            // 验证失败 输出错误信息
            return jsonReturn(0, [], $e->getError());
        }
        //处理参数
        $params['safe_code'] = substr(md5(uniqid()), 5, 10);
        $value = $params['password'] . $params['safe_code'];
        $params['password'] = password_hash($value, PASSWORD_DEFAULT);
        $params['create_time'] = time();
        $params['update_time'] = time();
        //写入管理员
        $id = Admin::insertGetId($params);
        if ($id) {
            return jsonReturn(1, ['id' => $id], '添加成功');
        }
        return jsonReturn(0, [], '添加失败');
    }

    /**
     * 编辑管理员
     * @param array $params
     * @return Json
     */
    public function edit(array $params): Json
    {
        //超级管理员权限
        $admin_id = WS_ADMIN_ID;
//        if ($admin_id !== 1 and $admin_id != $params['id']) {
//            return jsonReturn(0, [], '只能编辑自己的信息');
//        }
        //数据验证
        try {
            validate(AdminValidate::class)->scene('edit')->check($params);
        } catch (ValidateException $e) {
            return jsonReturn(0, [], $e->getError());
        }
        //查询当前id是否存在
        $Model = Admin::where(['id' => $params['id'], 'closed' => 0])->find();
        if (!$Model) {
            return jsonReturn(0, [], '管理员不存在');
        }
        //验证手机号是否唯一
        if ($params['phone'] != $Model->phone) {
            $res = Admin::findOne(['phone' => $params['phone'], 'closed' => 0]);
            if ($res) {
                return jsonReturn(0, [], '此手机号已存在');
            }
        }
        //修改时间
        $params['update_time'] = time();
        //编辑
        $res = $Model->save($params);
        if ($res) {
            return jsonReturn(1, [], '编辑成功');
        }
        return jsonReturn(0, [], '编辑失败');
    }

    /**
     * 删除管理员
     * @param int $id
     * @return Json
     */
    public function del(int $id): Json
    {
        //超级管理员权限
        if ($id == 1) {
            return jsonReturn(0, [], '不能删除最高管理员账号');
        }
        //查询当前id是否存在
        $res = Admin::findOne(['id' => $id, 'closed' => 0]);
        if (!$res) {
            return jsonReturn(0, [], '管理员不存在');
        }
        //删除
        $res = Admin::deleteData(['id' => $id]);
        if ($res) {
            //删除执行退出
            JwtService::userAdminLogout($id, 'admin');
            return jsonReturn(1, [], '删除成功');
        }
        return jsonReturn(0, [], '删除失败');
    }

    /**
     * 禁用或启用管理员
     * @param int $id
     * @param int $enable
     * @return Json
     */
    public function enable(int $id, int $enable): Json
    {
        //超级管理员权限
        if ($id == 1) {
            return jsonReturn(0, [], '不能禁用最高管理员账号');
        }
        //判断参数
        if (!in_array($enable, [0, 1])) {
            return jsonReturn(0, [], '参数错误');
        }
        //查询管理员
        $Model = Admin::where(['id' => $id, 'closed' => 0])->find();
        if (!$Model) {
            return jsonReturn(0, [], '管理员不存在');
        }
        //禁用执行退出
        if ($enable == 0) {
            JwtService::userAdminLogout($id, 'admin');
        }
        //编辑
        $params['enable'] = $enable;
        $params['update_time'] = time();
        $res = $Model->save($params);
        if ($res) {
            return jsonReturn(1, []);
        }
        return jsonReturn(0, [], '操作失败');
    }

    /**
     * 管理员修改密码
     * @param int $id
     * @param string $new_password
     * @return Json
     */
    public function editPwd(int $id, string $new_password): Json
    {
        //超级管理员权限
        $admin_id = WS_ADMIN_ID;
        if ($id == 1 and $admin_id != 1) {
            return jsonReturn(0, [], '不能修改最高管理员密码');
        }
        $new_password = RsaPassword::privateDecrypt($new_password);
        //查询管理员信息
        $user = Admin::findOne(['id' => $id, 'closed' => 0]);
        if (!$user) {
            return jsonReturn(0, [], '管理员不存在');
        }
        //加密
        $safe_code = substr(md5(uniqid()), 5, 10);
        $password = password_hash($new_password . $safe_code, PASSWORD_DEFAULT);
        //保存至数据库
        $params = ['password' => $password, 'safe_code' => $safe_code, 'update_time' => time()];
        $res = Admin::update($params, ['id' => $id]);
        if ($res) {
            return jsonReturn(1, [], '修改成功');
        }
        return jsonReturn(0, [], '修改失败');
    }

    /**
     * 管理员修改头像
     * @return Json
     */
    public function modifyAvatar(): Json
    {
        $admin_id = WS_ADMIN_ID;
        $file = request()->file('picture');
        //判断管理员是否存在
        $Model = Admin::where(['id' => $admin_id, 'closed' => 0,])->find();
        if (!$Model) {
            return jsonReturn(0, [], '管理员不存在');
        }
        //原头像
        $old_avatar = $Model->avatar;
        //处理上传图片信息
        $picture = ImgUpload::imgUploadAliyun($file, 'avatar', 500, 500, 0);
        //更新数据库
        $res = $Model->save(['avatar' => $picture['src']]);
        if ($res) {
            //删除原头像
            $aliyunOss = new AliyunOss();
            $aliyunOss->deleteObject($old_avatar);
            return jsonReturn(1, $picture, '修改成功');
        }
        return jsonReturn(0, [], '修改失败');
    }


}
